/**
 *	The NeuroCoSA Toolkit
 *	Copyright (C) 2003-6 Stuart Meikle.
 *
 *	This is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Lesser General Public
 *	License as published by the Free Software Foundation; either
 *	version 2.1 of the License, or (at your option) any later version.
 *
 *	This library is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *	Lesser General Public License for more details.
 *
 * @author	Stuart Meikle
 * @version	2006-halloween(mk2)
 * @license	LGPL
 */
package org.stumeikle.NeuroCoSA;


// demo user classes
import java.util.*;
import java.lang.*;
import org.stumeikle.NeuroCoSA.AutoCluster.AutoClusterMemoryControl;
import org.stumeikle.NeuroCoSA.AutoCluster.AutoClusterMemory;

// FUTURE: signal strength here needs to really be controlled by the cortex
// strength should be related to the position in the hierarchy.

public class AutoClusterSimpleNeuron extends SimpleNeuron implements AutoClusterNeuronIF
{
    double			iSL, iSD;
    boolean			iReceivedACMInput;
    String			iDbg;

    public AutoClusterSimpleNeuron(Layer l)
    {
	super(l);
	iDbg = new String("jam");
	iReceivedACMInput =false;
    }

    public	String	getDEBUGLabel()	
    {
	//should be overloaded by the user
	return iDbg; //((AutoClusterMemory)getData()).getDEBUGLabel();
    }

    public DataBlock	createCortexOutput(boolean l)
    {
	return null;
    }

    public void		storeACMInput()
    {
	//store the updated centroid info...
	//take in the values stored within the ACM structure and load into our own
	//local vars
	AutoClusterMemory	acm = (AutoClusterMemory)getData();
				//shouldn't be possible that acm == null ... ?
	
	double			dfroml = acm.getDistanceFromLearnValue();
	double			dfromd = acm.getTestDistance();
	long			ltime  = acm.getLearnTime();
	long			dtime  = acm.getTestTime();

	//translate the distances into firing strengths -> closer distances causing stronger firing
	if (ltime != getLayer().getTime())			iSL = 0.0;
	else
	{
	    if (dfroml == AutoClusterMemory.UNDEFINED_DISTANCE)	iSL = 0.0;
	    else
	    {
		iSL = Neuron.default_excitation_value / ((dfroml/30.0) + 1.0 );

/*
		distance calibrations here need to be automatic
		if we know that xx % of all measurements fall within the
		range of the bin we can calculate how the firing strength should drop 
		off.
		
		but theres no direct relationship between the size of the bin and the
		distribution. so tricky to do the calcs. 
		darn . could split it with nearest neighbour but ... its a bit < ideal.
		
*/		
	    }
	}

	if (dtime != getLayer().getTime())			iSD = 0.0;
	else
	{
	    if (dfromd == AutoClusterMemory.UNDEFINED_DISTANCE)	iSD = 0.0;
	    else
	    {
		iSD = 10.0 * Neuron.default_excitation_value / ((dfromd/60.0) + 1.0 );
	    }
	}
	
	//store the values in the vesicles... nope.
	iReceivedACMInput = true;
    }


   /** override the process vesicle method 
    */
    public	void		processVesicle( Vesicle v, Synapse s )
    {
	//extract the info needed from the lobe ptr vesicles
    	//map to the new space and carry on as normal

	if ( iReceivedACMInput == true )
	{
	    //pass on the values to the base classes
	    if (iSL > 0.0)	simpleUpdateLearnSig( iSL, s );
	    if (iSD > 0.0)	simpleUpdateDriveSig( iSD, s );

	    iReceivedACMInput =false;
	}
    
	//now process as normal
        if (v!=null)
	{       
	    switch( v.getType())
	    {
		//incoming vesicle is a learn vesicle.
		//set pointer according to the winner in the output lobe
	        case Vesicle.LEARN_VESICLE:
		        processLearn( v, s );
			break;
		case Vesicle.DRIVE_VESICLE:
			processDrive( v, s );
			break;		        
		default:
			;
	    }
	}
    }  
}
